using System;
using System.Text;

namespace EntitiesView.Editor
{
    public class EntityDataProcessGenerater
{
    public Type[] buffElementTypes;
    public Type[] componentDataTypes;
    StringBuilder buffString;

    public void GenerateEmpty(string path)
    {
        buffString = new StringBuilder();
        buffString.AppendLine(@"
using Unity.Entities;

namespace EntitiesViewer.Editor
{
    public static class EntityDataProcess
    {
        public static string IBuffElementDataToString(string name,Entity entity){
            return string.Empty;
        }
        
        public static string ComponentDataToString(string name,Entity entity){
            return string.Empty;
        }
    }
}");
        string totalPath = System.IO.Path.Combine(path, "EntityDataProcess.cs");
        if(System.IO.File.Exists(totalPath))
        {
            using var stream = System.IO.File.OpenWrite(totalPath);
            stream.SetLength(0);
            stream.Write(Encoding.UTF8.GetBytes(buffString.ToString()));
            stream.Flush();
            stream.Close();
        }
        else
        {
            using var stream = System.IO.File.CreateText(System.IO.Path.Combine(path, "EntityDataProcess.cs"));
            stream.WriteLine(buffString.ToString());
            stream.Flush();
            stream.Close();
        }
    }

    public void Generate(string path)
    {
        buffString = new StringBuilder();
        buffString.AppendLine(@"
using System;
using System.Text;
using Unity.Entities;

namespace EntitiesViewer.Editor
{
    public static class EntityDataProcess
    {");
        WriteIBuffElementData();
        WriteComponentData();
        buffString.AppendLine("   }\n}");

        string totalPath = System.IO.Path.Combine(path, "EntityDataProcess.cs");
        if(System.IO.File.Exists(totalPath))
        {
            using var stream = System.IO.File.OpenWrite(totalPath);
            stream.SetLength(0);
            stream.Write(Encoding.UTF8.GetBytes(buffString.ToString()));
            stream.Flush();
            stream.Close();
        }
        else
        {
            using var stream = System.IO.File.CreateText(System.IO.Path.Combine(path, "EntityDataProcess.cs"));
            stream.WriteLine(buffString.ToString());
            stream.Flush();
            stream.Close();
        }
    }
    void WriteIBuffElementData()
    {
        buffString.AppendLine(@"
        public static string IBuffElementDataToString(string name,Entity entity)
        {");
        if (buffElementTypes != null)
        {
            buffString.AppendLine("            var entityMgr = World.DefaultGameObjectInjectionWorld.EntityManager;");

            for (int i = 0; i < buffElementTypes.Length; ++i)
            {
                var type = buffElementTypes[i];
                if (i == 0)
                    buffString.AppendLine($"            if(name.Equals(\"{type.FullName}\"))");
                else
                    buffString.AppendLine($"            else if(name.Equals(\"{type.FullName}\"))");
                buffString.AppendLine(@"            {");
                buffString.AppendLine($"                var datas = entityMgr.GetBuffer<{type.FullName}>(entity);");
                buffString.AppendLine($"                Type type = typeof({type.FullName});");
                buffString.AppendLine($"                var fields = type.GetFields();");
                buffString.AppendLine($"                StringBuilder sb = new StringBuilder();");
                buffString.AppendLine($"                for(int i = 0; i < datas.Length; i++)");
                buffString.AppendLine("                {");
                buffString.AppendLine($"                    var item = datas[i];");
                buffString.AppendLine($"                    sb.AppendLine($\"{{type.FullName}}[{{i}}]\");");
                buffString.AppendLine($"                    foreach (var field in fields)");
                buffString.AppendLine("                    {");
                buffString.AppendLine("                        switch(field.Name)");
                buffString.AppendLine("                        {");

                var fields = type.GetFields();
                string stringParam = EntityViewerConfig.Instance.Codition(type);

                foreach (var field in fields)
                {
                    buffString.AppendLine($"                            case \"{field.Name}\":");
                    if (field.FieldType.Name.Contains("e__FixedBuffer"))
                    {
                        buffString.AppendLine(@"                                unsafe
                                {");
                        buffString.AppendLine($"                                    sb.Append(\"    {field.Name}: [\");");
                        buffString.AppendLine($"                                    var length = {stringParam};");
                        buffString.AppendLine(@"
                                    for(int x = 0;x<length;++x)
                                    {
                                        if(x == 0)");
                        buffString.AppendLine($"                                            sb.Append($\"{{item.{field.Name}[x]}}\");");
                        buffString.AppendLine($"                                         else");
                        buffString.AppendLine($"                                            sb.Append($\",{{item.{field.Name}[x]}}\");");
                        buffString.AppendLine("                                    }");
                        buffString.AppendLine("                                    sb.Append(\"]\\r\\n\");");
                        buffString.AppendLine("                            }");
                    }
                    else
                    {
                        buffString.AppendLine($"                                sb.AppendLine($\"    {field.Name}: {{item.{field.Name}}}\");");
                    }
                    buffString.AppendLine($"                            break;");
                }
                buffString.AppendLine("                        }");
                buffString.AppendLine("                    }");
                buffString.AppendLine("                }");
                buffString.AppendLine("                return sb.ToString();");
                buffString.AppendLine("            }");
            }
        }
        buffString.AppendLine(@"
            return string.Empty;
        }");
    }

    void WriteComponentData()
    {
        buffString.AppendLine(@"
        public static string ComponentDataToString(string name,Entity entity)
        {");
        if (componentDataTypes != null)
        {
            buffString.AppendLine("            var entityMgr = World.DefaultGameObjectInjectionWorld.EntityManager;");
            int createCount = 0;
            for (int i = 0; i < componentDataTypes.Length; ++i)
            {
                var type = componentDataTypes[i];

                var fields = type.GetFields();
                if (fields.Length == 0)
                    continue;
                if (createCount == 0)
                    buffString.AppendLine($"            if(name.Equals(\"{type.FullName}\"))");
                else
                    buffString.AppendLine($"            else if(name.Equals(\"{type.FullName}\"))");
                createCount++;
                buffString.AppendLine(@"            {");
                buffString.AppendLine($"                var item = entityMgr.GetComponentData<{type.FullName}>(entity);");
                buffString.AppendLine($"                Type type = typeof({type.FullName});");
                buffString.AppendLine($"                var fields = type.GetFields();");
                buffString.AppendLine($"                StringBuilder sb = new StringBuilder();");
                buffString.AppendLine($"                sb.AppendLine($\"{{type.FullName}}\");");
                buffString.AppendLine($"                foreach (var field in fields)");
                buffString.AppendLine("                {");
                buffString.AppendLine("                    switch(field.Name)");
                buffString.AppendLine("                    {");

                string stringParam = EntityViewerConfig.Instance.Codition(type);

                foreach (var field in fields)
                {
                    buffString.AppendLine($"                        case \"{field.Name}\":");
                    if (field.FieldType.Name.Contains("e__FixedBuffer"))
                    {
                        buffString.AppendLine(@"                            unsafe
                            {
                                sb.Append(""    TempValues: ["");");
                        buffString.AppendLine($"                                    var length = {stringParam};");
                        buffString.AppendLine(@"
                                    for(int x = 0;x<length;++x)
                                    {
                                        if(x == 0)");
                        buffString.AppendLine($"                                            sb.Append($\"{{item.{field.Name}[x]}}\");");
                        buffString.AppendLine($"                                         else");
                        buffString.AppendLine($"                                            sb.Append($\",{{item.{field.Name}[x]}}\");");
                        buffString.AppendLine("                                    }");
                        buffString.AppendLine("                                    sb.Append(\"]\\r\\n\");");
                        buffString.AppendLine("                            }");
                    }
                    else
                    {
                        buffString.AppendLine($"                            sb.AppendLine($\"    {field.Name}: {{item.{field.Name}}}\");");
                    }
                    buffString.AppendLine($"                        break;");
                }
                buffString.AppendLine("                    }");
                buffString.AppendLine("                }");
                buffString.AppendLine("                return sb.ToString();");
                buffString.AppendLine("            }");
            }
        }
        buffString.AppendLine(@"
            return string.Empty;
        }");
    }
}
}

